<?php

/**
 * Created by PhpStorm.
 * User: li
 * Date: 15-10-13
 * Time: 上午10:58
 */
require_once('phpass-0.1/PasswordHash.php');

define('STATUS_ACTIVATED', '1');
define('STATUS_NOT_ACTIVATED', '0');
class Api_auth
{
    private $error = array();
    private $user = array();
    private $token = '';
    function __construct(){
        $this->ci =& get_instance();

        $this->ci->load->config('auth', TRUE);
        $this->ci->load->database();
        $this->ci->load->model('auth/users');
        $this->ci->load->model('auth/user_active');
        $this->ci->load->library('Xxtea.php');
    }

    /**
     * @return string
     */
    function get_token(){
        return $this->token;
    }

    /**
     * @return array
     */
    function get_user(){
        return $this->user;
    }

    /**
     * @return array
     */
    function get_error(){
        return $this->error;
    }

    /**
     * @param $user_id
     * @param $token
     * @param int $expire
     * @return bool
     */
    function decode($user_id,$token , $expire=0){
        $data = base64_decode(strtr($token, '_-', '+/'));
        if(!$data) { array_push($this->error,array('auth'=>'Authentication failed')); }

        $data = $this->ci->xxtea->decrypt($data, $this->ci->config->item('api_key', 'auth'));
        if(!$data) { array_push($this->error,array('auth'=>'Authentication failed')); }

        $firstPos = strpos($data, ':');
        $lastPos  = strrpos($data, ':');
        if($firstPos===false or $lastPos===false) {array_push($this->error,array('auth'=>'Authentication failed'));}

        $res = array();
        $res['user_id'] = substr($data, 0, $firstPos);
        $res['mobile'] = substr($data, $lastPos+1);
        $res['time'] = substr($data, $firstPos+1, $lastPos-$firstPos-1);
        if($user_id!=$res['user_id']){
            array_push($this->error,array('auth'=>'Authentication failed'));
        }
        if($expire){
            if(time()-$res['time']>$expire){
                array_push($this->error,array('auth'=>'Authentication timeout'));
                return false;
            }
        }
        $this->user = $res;
        return true;
    }

    /**
     * 登录操作
     *
     * @param   string
     * @param   string
     * @param   bool
     * @param   array
     * @return bool
     */
    function login($login, $password,  $login_by_email = false ,$device=array()){
        if ((strlen($login) > 0) AND (strlen($password) > 0) ) {
            if ($login_by_email) {
                $get_user_func = 'get_user_by_email';
            } else {
                $get_user_func = 'get_user_by_mobile';
            }
            if (!is_null($user = $this->ci->users->$get_user_func($login))) {
                $hasher = new PasswordHash(
                    $this->ci->config->item('phpass_hash_strength', 'auth'),
                    $this->ci->config->item('phpass_hash_portable', 'auth'));
                //密码正确
                if ($hasher->CheckPassword($password, $user->password)) {
                    if ($user->banned == 1) {                                    // 用户被禁止？
                        $this->error = array('banned' => $user->ban_reason);
                    } else {
                        $this->encode($user);
                        $this->user=$user;
                        $user = array(
                            'user_id'	=> $user->id,
                            'username'	=> $user->username,
                            'email'     => $user->email,
                            'mobile'    => $user->mobile,
                            'status' => ($user->activated == 1) ? STATUS_ACTIVATED : STATUS_NOT_ACTIVATED,
                        );
                        $this->set_logged_session($user);
                        $this->clear_login_attempts($login);
                        $this->ci->users->update_login_info(
                            $user->id,
                            $this->ci->config->item('login_record_ip', 'auth'),
                            $this->ci->config->item('login_record_time', 'auth'));
                        return TRUE;
                    }
                }else{
                    $this->increase_login_attempt($login);
                    $this->error = array('password' => '密码错误');
                }
            }
            else {
                $this->increase_login_attempt($login);
                $this->error = array('login' => '账号不存在');
            }
        }
        return FALSE;
    }

    /**
     * @param $user
     */
    private function encode($user){
        $mobile = ($user->mobile>0)?$user->mobile:($user->email?$user->email:'none');
        $enc = $this->ci->xxtea->encrypt("{$user->id}:{$mobile}".time(), $this->ci->config->item('api_key', 'auth'));
        $this->token = strtr(base64_encode($enc), '+/=', '_- ');
    }


    /**
     * 退出登录
     *
     */
    function logout()
    {
       unset($this->user);
       unset($this->token);
       unset($this->error);
    }
    /**
     * 获取ID
     *
     * @return	string
     */
    function get_user_id()
    {
        return $this->user['user_id'];
    }



    /**
     * 获取手机
     *
     * @return	string
     */
    function get_mobile()
    {
        return $this->user['mobile'];
    }

    /**
     * 创建一个新用户
     *
     * @param	string
     * @param	string ['mobile','email']
     * @param	string
     * @param	string
     * @param	array
     * @return	array
     */
    function create_user($username, $type , $account , $password ,$extend = [])
    {
        if($type!='email' && $type!='mobile') {
            $this->error = array('type' => '帐户类型暂不支持');
        }else{
            $fun = 'is_'.$type.'_available';
            if ((strlen($username) > 0) AND !$this->ci->users->is_username_available($username)) {
                $this->error = array('username' => '该用户名已注册');

            } elseif (!$this->ci->users->$fun($account) AND $account) {
                $this->error = array($type => '该'.(($type=='email')?'邮箱':'手机号').'已注册');

            } else {

                $hasher = new PasswordHash(
                    $this->ci->config->item('phpass_hash_strength', 'auth'),
                    $this->ci->config->item('phpass_hash_portable', 'auth'));
                $hashed_password = $hasher->HashPassword($password);

                $data = array(
                    'username'	=> $username,
                    'password'	=> $hashed_password,
                    $type		=> $account,
                    'last_ip'	=> $this->ci->input->ip_address(),
                );


                $data = array_merge($data, $extend);
                if (!is_null($res = $this->ci->users->create_user($data, false))) {
                    if ($type == 'email') {
                        $new_email_key = md5(rand().microtime());
                        $this->has_key_exists($res['user_id'],'email_first');
                        $this->ci->user_active->insert_new_key(
                            $res['user_id'],$account,NULL,$new_email_key,'email_first');
                    }
                    $data['user_id'] = $res['user_id'];
                    $data['password'] = $password;
                    //设置一个一次有效的SESSION
                    //$this->ci->session->set_flashdata($this->ci->config->item('email_active_user_id','auth'),$res['user_id']);
                    unset($data['last_ip']);
                    return $data;
                }
            }
        }
        return NULL;
    }
    /**
     * 检测key是否存在，存在删除重写
     *
     * @param $user_id
     * @param $type
     */
    private function has_key_exists($user_id,$type){
        $active_id = $this->ci->user_active->func_key_exists($user_id,$type);
        if($active_id){
            $this->ci->user_active->delete_active($user_id,$type);
        }
    }
    /**
     * 检测用户名是否可用
     *
     * @param	string
     * @return	bool
     */
    function is_username_available($username)
    {
        return ((strlen($username) > 0) AND $this->ci->users->is_username_available($username));
    }

    /**
     * 检测邮箱是否可用
     *
     * @param	string
     * @return	bool
     */
    function is_email_available($email)
    {
        return ((strlen($email) > 0) AND $this->ci->users->is_email_available($email));
    }

    /**
     * 检测手机是否可用
     *
     * @param	string
     * @return	bool
     */
    function is_mobile_available($mobile)
    {
        return ((strlen($mobile) > 0) AND $this->ci->users->is_mobile_available($mobile));
    }


    /**
     * 记录错误的登录次数
     *
     * @param string
     */
    private function increase_login_attempt($login)
    {
        if ($this->ci->config->item('login_count_attempts', 'auth')) {
            if (!$this->is_max_login_attempts_exceeded($login)) {
                $this->ci->load->model('auth/login_attempts');
                $this->ci->login_attempts->increase_attempt($this->ci->input->ip_address(), $login);
            }
        }
    }
    /**
     * 清除错误登录次数
     *
     *  @param string
     */
    private function clear_login_attempts($login)
    {
        if ($this->ci->config->item('login_count_attempts', 'auth')) {
            $this->ci->load->model('auth/login_attempts');
            $this->ci->login_attempts->clear_attempts(
                $this->ci->input->ip_address(),
                $login,
                $this->ci->config->item('login_attempt_expire', 'auth'));
        }
    }

    /**
     * 检测用户是否超过最多登录次数
     *
     * @param	string
     * @return	bool
     */
    function is_max_login_attempts_exceeded($login)
    {
        if ($this->ci->config->item('login_count_attempts', 'auth')) {
            $this->ci->load->model('auth/login_attempts');
            return $this->ci->login_attempts->get_attempts_num($this->ci->input->ip_address(), $login)
            >= $this->ci->config->item('login_max_attempts', 'auth');
        }
        return FALSE;
    }

    function set_logged_session($user){
        $_SESSION['login_user']= array(
            'user_id'	=> $user['user_id'],
            'username'	=> $user['username'],
            'email'     => '',
            'mobile'    => '',
            'status'	=> true,
        );
        //写入用户和session关系
        //                        $this->ci->config->load('redis');
        //                        $redis_config = $this->ci->config->item('redis');
        //                        $this->ci->load->library('Redis_session_relation',$redis_config);
        //                        $this->ci->redis_session_relation->set_relation($user->id,session_id());
    }


}